package com.tree.backend.aspect;

import cn.hutool.json.JSONUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * Controller层日志切面
 * 用于拦截所有Controller方法的调用，记录请求参数、返回值和执行时间
 */
@Aspect
@Component
public class ControllerLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(ControllerLogAspect.class);
    
    // 敏感字段列表
    private static final Set<String> SENSITIVE_FIELDS = new HashSet<>(Arrays.asList(
            "pwd", "password", "token", "secret", "key", "credential", 
            "authorization", "auth", "passwd"
    ));

    // 定义切点，拦截所有Controller类中的方法
    @Pointcut("execution(* com.tree.backend.controller.*.*(..))")
    public void controllerPointCut() {
    }

    // 环绕通知
    @Around("controllerPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        // 获取请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        
        // 获取方法信息
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        
        // 记录请求开始
        logger.info("[请求开始] {}.{} - Request URL: {}, Method: {}",
                className, methodName, request.getRequestURL().toString(), request.getMethod());
        
        // 获取并记录请求参数（过滤敏感信息）
        Object[] args = point.getArgs();
        if (args != null && args.length > 0) {
            String filteredParams = filterSensitiveFields(args);
            logger.info("[请求参数] {}.{} - Request Parameters: {}", className, methodName, filteredParams);
        }
        
        // 执行方法
        Object result;
        try {
            result = point.proceed();
            
            // 记录返回值（过滤敏感信息）
            if (result != null) {
                String filteredResult = filterSensitiveFields(result);
                logger.info("[响应参数] {}.{} - Response: {}", className, methodName, filteredResult);
            }
        } catch (Exception e) {
            // 记录异常
            logger.error("[记录异常] {}.{} - Error: {}", className, methodName, e.getMessage(), e);
            throw e;
        } finally {
            // 记录执行时间
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime;
            logger.info("[响应结束] {}.{} - Execution Time: {} ms\n", className, methodName, executionTime);
        }
        
        return result;
    }

    /**
     * 过滤敏感字段
     * @param object 要过滤的对象
     * @return 过滤后的JSON字符串
     */
    private String filterSensitiveFields(Object object) {
        try {
            cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(object);
            filterSensitiveFieldsRecursive(jsonObject);
            return jsonObject.toString();
        } catch (Exception e) {
            // 如果对象不是JSON格式，尝试转换为JSONArray
            try {
                cn.hutool.json.JSONArray jsonArray = JSONUtil.parseArray(object);
                filterSensitiveFieldsRecursive(jsonArray);
                return jsonArray.toString();
            } catch (Exception ex) {
                // 如果都不是，直接返回对象的字符串表示
                return object.toString();
            }
        }
    }

    /**
     * 过滤敏感字段（数组版本）
     * @param args 要过滤的参数数组
     * @return 过滤后的JSON字符串
     */
    private String filterSensitiveFields(Object[] args) {
        try {
            cn.hutool.json.JSONArray jsonArray = JSONUtil.parseArray(args);
            filterSensitiveFieldsRecursive(jsonArray);
            return jsonArray.toString();
        } catch (Exception e) {
            return Arrays.toString(args);
        }
    }
    
    /**
     * 递归过滤JSONObject中的敏感字段
     * @param jsonObject 要过滤的JSONObject
     */
    private void filterSensitiveFieldsRecursive(cn.hutool.json.JSONObject jsonObject) {
        if (jsonObject == null) {
            return;
        }
        
        for (String key : jsonObject.keySet()) {
            // 检查是否是敏感字段
            if (isSensitiveField(key)) {
                jsonObject.set(key, "******");
            } else {
                // 获取字段值
                Object value = jsonObject.get(key);
                // 递归处理嵌套的JSONObject
                if (value instanceof cn.hutool.json.JSONObject) {
                    filterSensitiveFieldsRecursive((cn.hutool.json.JSONObject) value);
                } 
                // 递归处理嵌套的JSONArray
                else if (value instanceof cn.hutool.json.JSONArray) {
                    filterSensitiveFieldsRecursive((cn.hutool.json.JSONArray) value);
                }
                // 对于字符串值，也可以检查是否包含敏感信息（可选）
                else if (value instanceof String && isSensitiveContent((String) value)) {
                    jsonObject.set(key, "******");
                }
            }
        }
    }
    
    /**
     * 递归过滤JSONArray中的敏感字段
     * @param jsonArray 要过滤的JSONArray
     */
    private void filterSensitiveFieldsRecursive(cn.hutool.json.JSONArray jsonArray) {
        if (jsonArray == null) {
            return;
        }

        for (Object value : jsonArray) {
            // 递归处理嵌套的JSONObject
            if (value instanceof cn.hutool.json.JSONObject) {
                filterSensitiveFieldsRecursive((cn.hutool.json.JSONObject) value);
            }
            // 递归处理嵌套的JSONArray
            else if (value instanceof cn.hutool.json.JSONArray) {
                filterSensitiveFieldsRecursive((cn.hutool.json.JSONArray) value);
            }
        }
    }
    
    /**
     * 判断字段名是否为敏感字段
     * @param fieldName 字段名
     * @return 是否为敏感字段
     */
    private boolean isSensitiveField(String fieldName) {
        if (fieldName == null) {
            return false;
        }
        // 转小写进行比较，忽略大小写
        String lowerCaseFieldName = fieldName.toLowerCase();
        for (String sensitiveField : SENSITIVE_FIELDS) {
            // 检查是否包含敏感字段名
            if (lowerCaseFieldName.contains(sensitiveField)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 判断字符串内容是否包含敏感信息（可选增强）
     * @param content 字符串内容
     * @return 是否包含敏感信息
     */
    private boolean isSensitiveContent(String content) {
        // 这里可以添加额外的敏感内容检测逻辑
        // 例如检测token格式、密码格式等
        if (content == null) {
            return false;
        }
        
        // 简单检测JWT token格式（以eyJ开头，以.结尾）
        return content.startsWith("eyJ") && content.contains(".");
        
        // 可以添加更多的敏感内容检测规则
    }
}